package com.naiterui.ehp.bp.utils.biz;

import java.util.HashSet;
import java.util.Set;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.naiterui.ehp.bp.utils.lang.StringUtil;

/**
 * 名称操作辅助类

 * @since 2.2.0
 */
public class NameUtils {

    /**
     * 姓名匹配正则：<code>VALIDATE_REGEX_NAME</code>
     * 仅允许输入汉字、字母（大小写均可）、阿拉伯数字及小数点，不允许输入其他字符。长度统一由LimitValueConfig控制。
     */
    public static final String VALIDATE_REGEX_NAME = "^[A-Za-z0-9\u4e00-\u9fa5\u0020-/:;()$&@\".,?!'\\[\\]{}#%\\^*+=_\\\\|~<>€£¥•·]*";

    /**
     * 处方、病历 用户姓名匹配正则：<code>VALIDATE_REGEX_USER_NAME</code>
     * 仅允许输入汉字、字母（大小写均可），不允许输入其他字符
     */
    public static final String VALIDATE_REGEX_USER_NAME = "^([A-Za-z]|[\\u4E00-\\u9FA5])+$";
    /**
     * 医院匹配正则：<code>VALIDATE_REGEX_HOSIPITAL</code>
     * 输入中文、英文及标点符号（全半角均可）、数字。不能包含表情符号。长度统一由LimitValueConfig控制。
     */
    public static final String VALIDATE_REGEX_HOSIPITAL = "^[A-Za-z0-9\u4e00-\u9fa5\u3000-\u301e\ufe10-\ufe19\ufe30-\ufe44\ufe50-\ufe6b\uff01-\uffee-/:;()$&@\".,?!'\\[\\]{}#%\\^*+=_\\\\|~<>€£¥•]*";
    /**
     * 科室匹配正则：<code>VALIDATE_REGEX_DEPARTMENT</code>
     * 输入中文、英文及标点符号（全半角均可）、数字。不能包含表情符号。长度统一由LimitValueConfig控制。
     */
    public static final String VALIDATE_REGEX_DEPARTMENT = "^[A-Za-z0-9\u4e00-\u9fa5\u3000-\u301e\ufe10-\ufe19\ufe30-\ufe44\ufe50-\ufe6b\uff01-\uffee-/:;()$&@\".,?!'\\[\\]{}#%\\^*+=_\\\\|~<>€£¥•]*";
    /**
     * 个人简介、擅长等匹配正则：<code>VALIDATE_REGEX_DEPARTMENT</code>
     * 输入中文、英文及标点符号（全半角均可）、数字。不能包含表情符号，不大于300个长度
     */
    public static final String VALIDATE_REGEX_OTHERS = "^[A-Za-z0-9\u4e00-\u9fa5\u3000-\u301e\ufe10-\ufe19\ufe30-\ufe44\ufe50-\ufe6b\uff01-\uffee\\s-/:;()$&@\".,?!'\\[\\]{}#%\\^*+=_\\\\|~<>€£¥•]*";
    /**
     * 患者分组匹配正则:
     * 输入数字,字母和中文。长度统一由LimitValueConfig控制。
     */
    public static final String VALIDATE_REGEX_PT_GROUP_NAME = "^[A-Za-z0-9\u4e00-\u9fa5]*";

    /**
     * 日志对象：<code>LOGGER</code>
     */
    private static final Logger LOGGER = LoggerFactory.getLogger(NameUtils.class);

    /**
     * 首字母大写
     * NameUtils.getFirstUpperName()

     * @Date 2016年3月6日
     * @since 2.2.0
     * @param source 待处理字符串
     * @return
     */
    public static String getFirstUpperName(String source) {
        if (StringUtils.isBlank(source)) {
            return null;
        }
        String firstChar = StringUtils.substring(source, 0, 1).toUpperCase();
        return firstChar + StringUtils.substring(source, 1);
    }

    /**
     * 首字母小写
     * NameUtils.getFirstLowerName()

     * @Date 2016年3月6日
     * @since 2.2.0
     * @param source 待处理字符串
     * @return
     */
    public static String getFirstLowerName(String source) {
        if (StringUtils.isBlank(source)) {
            return null;
        }
        String firstChar = StringUtils.substring(source, 0, 1).toLowerCase();
        return firstChar + StringUtils.substring(source, 1);
    }

    /**
     * 转换成骆驼命名法返回
     * NameUtils.getCamelName()

     * @Date 2016年3月6日
     * @since 2.2.0
     * @param source 待处理字符串
     * @return
     */
    public static String getCamelName(String source) {
        if (StringUtils.isBlank(source)) {
            return null;
        }
        source = StringUtils.lowerCase(source);
        // 去掉前面的_
        while (StringUtils.startsWith(source, "_")) {
            source = StringUtils.substring(source, 1);
        }
        // 去掉后面的_
        while (StringUtils.endsWith(source, "_")) {
            source = StringUtils.substring(source, 0, source.length() - 1);
        }

        StringBuilder sb = new StringBuilder();

        for (int i = 0; i < source.length(); i++) {

            char c = source.charAt(i);

            if (c == '_') {
                i++;
                sb.append(Character.toUpperCase(source.charAt(i)));
                continue;
            }
            sb.append(c);
        }

        return sb.toString();
    }

    /**
     * 将骆驼命名法反转成下划线返回
     * NameUtils.getUnderlineName()

     * @Date 2016年3月6日
     * @since 2.2.0
     * @param source 待处理字符串
     * @return
     */
    public static String getUnderlineName(String source) {

        if (StringUtils.isBlank(source)) {
            return null;
        }

        StringBuilder sb = new StringBuilder();

        for (int i = 0; i < source.length(); i++) {

            char c = source.charAt(i);

            if (i > 0 && Character.isUpperCase(c)) {
                sb.append("_");
            }

            sb.append(c);
        }

        return sb.toString().toLowerCase();
    }

    /**
     * 替换Emoji特殊表情(utf8mb4)
     * NameUtils.handleUtf8mb4()

     * @Date 2016年3月6日
     * @since 2.2.0
     * @param source 待处理字符串
     * @param replace 殊字符替换符(可为空)
     * @return
     */
    public static String handleUtf8mb4(String source, String replace) {

        LOGGER.info("handle Emoji code START ; sourceUnicode 【{}】,source 【{}】", StringUtil.encodeUnicode(source), source);

        // emoji 表情默认正则
        Set<String> regexSet = new HashSet<>();
        regexSet.add("[^\u0000-\uFFFF]");
        regexSet.add("[^\u0000-\uD7FF\uE000-\uFFFF]");

        // 调用默认替换
        String result = handleChar(source, replace, regexSet, null);

        if (StringUtils.isEmpty(source)) {
            LOGGER.info("handle special char ; source is empty");
            return "";
        }

        return result;
    }

    /**
     * 给定自定义正则、特例，替换特殊字符
     * NameUtils.handleChar()

     * @Date 2016年3月6日
     * @since 2.2.0
     * @param source 待处理字符串
     * @param replace 特殊字符替换符(可为空)
     * @param regexSet 正则集合
     * @param instanceSet 特例Unicode集合
     * @return
     */
    public static String handleChar(String source, String replace, Set<String> regexSet, Set<String> instanceSet) {

        LOGGER.info("handle special char START ; sourceUnicode 【{}】,source 【{}】", StringUtil.encodeUnicode(source), source);

        if (StringUtils.isEmpty(source)) {
            LOGGER.info("handle special char ; source is empty");
            return "";
        }

        replace = null == replace ? "" : replace;

        // 处理缓存正则
        if (null != regexSet) {
            for (String regex : regexSet) {
                if (!StringUtils.isEmpty(source)) {
                    source = source.replaceAll(regex, replace);
                }
            }
        }

        // 处理缓存Unicode特例
        if (null != instanceSet) {
            for (String instance : instanceSet) {
                if (!StringUtils.isEmpty(source)) {
                    while (!StringUtils.isEmpty(source) && StringUtil.encodeUnicode(source).contains(instance)) {
                        source = StringUtil.decodeUnicode(StringUtil.encodeUnicode(source).replace(instance, replace));
                    }
                }
            }
        }

        LOGGER.info("handle special char END ; resultUnicode 【{}】,result 【{}】", StringUtil.encodeUnicode(source), source);
        return source;
    }

    /**
     * 判断字符串是否包换utf8mb4编码字符
     * NameUtils.containUtf8mb4()

     * @Date 2016年3月6日
     * @since 2.2.0
     * @param source 待判断字符串
     * @return
     */
    public static boolean containUtf8mb4(String source) {

        boolean result = false;
        if (StringUtils.isNotEmpty(source) && (source.matches("[^\u0000-\uFFFF]") || source.matches("[^\u0000-\uD7FF\uE000-\uFFFF]"))) {
            result = true;
        }
        return result;
    }

    /**
     * 替换中文标点符号为英文标点符号
     * @Description
     * @author wangchuan
     * @Date 2017年9月21日
     * @since V2.9.2
     * @param source
     * @return
     */
    public static String replaceChinesePunctuation(String source) {
        if (source == null) {
            return null;
        }
        return source.replaceAll("。", ".").replaceAll("，", ",").replaceAll("：", ":").replaceAll("；", ";").replaceAll("、", ",").replaceAll("！", "!")
                .replaceAll("（", "(").replaceAll("）", ")")
                // \u3008和\u3009
                .replaceAll("〈", "<").replaceAll("〉", ">")
                // \uff1c和\uff1e
                .replaceAll("＜", "<").replaceAll("＞", ">")
                // \u3010和\u3011
                .replaceAll("【", "[").replaceAll("】", "]")
                // \uff3b和\uff3d
                .replaceAll("［", "[").replaceAll("］", "]").replaceAll("《", "<").replaceAll("》", ">").replaceAll("☀", "*").replaceAll("～", "~")
                .replaceAll("＆", "&").replaceAll("／", "/")
                .replaceAll("？", "?")
                // 中文全角空格
                .replaceAll("\u3000", " ")
                // 中文Tab空格
                .replaceAll("\u0009", " ")
                // 换页符、换行符、回车符、制表符、垂直制表符等。多个空白符替换成一个
                .replaceAll("\\s+", " ");
    }
}
